package com.tansun.easycare.rule.codeblock.service.impl;

import java.io.File;
import java.io.FileFilter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import org.apache.commons.lang3.StringEscapeUtils;
import org.kie.api.io.ResourceType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.util.WebUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.tansun.easycare.rule.codeblock.dao.RuleCodeblockDao;
import com.tansun.easycare.rule.codeblock.entity.RuleCodeblock;
import com.tansun.easycare.rule.codeblock.entity.RuleCodeblockInfo;
import com.tansun.easycare.rule.codeblock.model.CodeblockVO;
import com.tansun.easycare.rule.codeblock.service.RuleCodeblockService;
import com.tansun.easycare.rule.common.DataCache;
import com.tansun.easycare.rule.common.FileUtils;
import com.tansun.easycare.rule.common.ResMessage;
import com.tansun.easycare.rule.common.jfun.JFun;
import com.tansun.easycare.rule.common.jfun.JFunParam;
import com.tansun.easycare.rule.common.model.ResponseVO;
import com.tansun.easycare.rule.common.service.RuleDrlParseService;
import com.tansun.easycare.rule.common.service.impl.RuleBaseServiceImpl;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.exception.DataEmptyException;
import com.tansun.easycare.rule.referencedata.entity.RuleReferenceData;
import com.tansun.easycare.rule.referencedata.service.RuleReferenceDataService;
import com.tansun.easycare.rule.rulemange.entity.RuleManage;
import com.tansun.easycare.rule.rulemange.model.RuleManageVO;
import com.tansun.easycare.rule.rulemange.service.RuleManageService;
import com.tansun.easycare.rule.ruleversion.entity.RuleVersioninfo;
import com.tansun.easycare.rule.ruleversion.service.RuleVersioninfoService;
import com.tansun.rule.api.IRuleService;
import com.tansun.rule.common.RuleModelTypeEnum;
import com.tansun.rule.model.toolbean.FunctionItem;
import com.tansun.rule.model.toolbean.RuleModel;
import com.tansun.rule.model.toolbean.RuleModel.RuleType;
import com.tansun.rule.model.toolbean.RuleResult;
import com.tansun.rule.utils.DroolsComplier;
import com.tansun.rule.utils.LoggerManager;
import com.tansun.rule.utils.StringUtils;

@Service
public class RuleCodeblockServiceImpl extends RuleBaseServiceImpl<RuleCodeblockDao, RuleCodeblock> implements RuleCodeblockService {

    protected transient Logger logger = LoggerFactory.getLogger(RuleCodeblockServiceImpl.class);
    @Autowired
    private RuleManageService ruleManageService;
    @Autowired
    private IRuleService ruleService;
    @Autowired
    private RuleVersioninfoService ruleVersioninfoService;
    @Autowired
    private RuleDrlParseService ruleDrlParseService;
    @Autowired
    private RuleReferenceDataService ruleReferenceDataService;
    
    private final static String MESSAGE_CODE_SUCCESS = "1";
    private final static String MESSAGE_CODE_FAILURE = "0";

    @Override
    public CodeblockVO findCodeblocks(String id, String projectCode) throws Exception {
        CodeblockVO result = new CodeblockVO();
        RuleManage ruleManage = ruleManageService.get(id);
        if (ruleManage == null)
            throw new BizException("E-000600");
        RuleCodeblock codeInfo = new RuleCodeblock();
        codeInfo.setManageId(ruleManage.getId());
        List<RuleCodeblock> codes = this.findList(codeInfo);
        if (codes != null && codes.size() > 0) {
            RuleCodeblock ruleCodeblock = codes.get(0);
            if (com.tansun.rule.common.RuleModelTypeEnum.RuleFunction.getCode().equals(ruleManage.getModelType())) {
                result.setFuncParams(ruleCodeblock.getParameters());
            }
            ruleCodeblock.setStrCodeBody(ruleCodeblock.getCodeBody());
            result.setRuleCodeblock(ruleCodeblock);
        }
        result.setRuleManage(ruleManage);
        return result;
    }
    
    public List<RuleCodeblock> findJFCodeblockList(String projectCode) {
        RuleManage queryManage = new RuleManage();
        queryManage.setModelType(RuleModelTypeEnum.RuleFunction.code);
        queryManage.setProjectCode(projectCode);
        List<RuleManage> list = ruleManageService.findList(queryManage);
        List<RuleCodeblock> rlist  = new ArrayList<RuleCodeblock>();
        for(RuleManage rm:list) {
            RuleCodeblock codeInfo = new RuleCodeblock();
            codeInfo.setManageId(rm.getId());
            List<RuleCodeblock> codes = this.findList(codeInfo);
            rlist.addAll(codes);
        };
		return rlist;
	}

    public String findCodeblocksByCode(String code, String projectCode) throws Exception {
        RuleManage queryManage = new RuleManage();
        queryManage.setCode(code);
        queryManage.setProjectCode(projectCode);
        RuleManage ruleManage = null;
        List<RuleManage> list = ruleManageService.findList(queryManage);
        if (list == null || list.size() == 0)
            throw new BizException("E-000600");
        ruleManage = list.get(0);
        RuleCodeblock codeInfo = new RuleCodeblock();
        codeInfo.setManageId(ruleManage.getId());
        List<RuleCodeblock> codes = this.findList(codeInfo);
        if (codes != null && codes.size() > 0) {
            RuleCodeblock ruleCodeblock = codes.get(0);
            return ruleCodeblock.getCodeBody();

        }
        return null;
    }

    @Override
    public ResponseVO save(CodeblockVO codeblockVO) throws BizException {
    	ResponseVO res = this.compileByFlow(codeblockVO);
        if (res.getStatus()==100) {
            return res;
        }
        RuleManage ruleManage = codeblockVO.getRuleManage();
        ruleManage.setModelType(RuleModelTypeEnum.CodeBlock.getCode());
        Date date = new Date();
        ruleManage.setUpdateDate(date);
        if(ruleManage.getCreateDate()==null) {
        	ruleManage.setCreateDate(date);
        }
       // ruleManageService.save(ruleManage);
        ruleManageService.saveOrUpdate(ruleManage);
        RuleCodeblock ruleCodeblock = codeblockVO.getRuleCodeblock();
        ruleCodeblock.setProjectCode(ruleManage.getProjectCode());
        ruleCodeblock.setManageId(ruleManage.getId());
        try {
            ruleCodeblock.setCodeBody(ruleCodeblock.getStrCodeBody());
            super.save(ruleCodeblock);
            
    		// 收集引用数据
    		Map<String, RuleReferenceData> ruleRefMap = new HashMap<String, RuleReferenceData>();
			ruleDrlParseService.collectReferenceData(ruleManage, ruleCodeblock.getCodeBody(), ruleRefMap);
			// 保存引用数据
			this.ruleReferenceDataService.saveReferenceData(ruleRefMap);

			String context = getFlowCode(codeblockVO);
            RuleVersioninfo versioninfo = new RuleVersioninfo();
            versioninfo.init(ruleManage, context);
            List<RuleVersioninfo> ruleList = this.ruleVersioninfoService.findList(versioninfo);
            if (ruleList != null && ruleList.size() > 0) {
                versioninfo = ruleList.get(0);
                versioninfo.setRuleContent(context);
            }
       	 	this.ruleVersioninfoService.save(versioninfo);
            res.setStatus(ResponseVO.OK);
            res.setDescription("保存成功");
        } catch (Exception e) {
        	res.setStatus(ResponseVO.ERROR);
        	res.setDescription(e.getMessage());
            LoggerManager.error(e.getMessage(), e, this.getClass());
        }
        
        return res;

    }

    @Override
    public ResponseVO saveFunc(CodeblockVO codeblockVO) throws BizException {
    	ResponseVO res = this.validateDrl(codeblockVO,false);
        if(StringUtils.isEmpty(codeblockVO.getRuleManage().getName())){
			throw new DataEmptyException("请输入函数名称");
		}
		if(StringUtils.isEmpty(codeblockVO.getRuleCodeblock().getFunctionName())){
			throw new DataEmptyException("请输入函数编码");
		}
		if(StringUtils.isEmpty(codeblockVO.getRuleCodeblock().getReturnType())){
			throw new DataEmptyException("请选择返回类型");
		}
		if(StringUtils.isEmpty(codeblockVO.getRuleCodeblock().getStrCodeBody())) {
			throw new DataEmptyException("函数代码不能为空");
		}
        //校验函数名称唯一
        RuleManage rm = new RuleManage();
        rm.setModelType(RuleModelTypeEnum.RuleFunction.getCode());
        rm.setStatus("1");
        rm.setProjectCode(codeblockVO.getRuleManage().getProjectCode());
        List<RuleManage> ruleManageListlist = ruleManageService.findList(rm);
        for (RuleManage manage : ruleManageListlist) {
            if (manage.getName().equals(codeblockVO.getRuleManage().getName()) && !manage.getCode().equals(codeblockVO.getRuleManage().getCode())) {
//                res.setCode(MESSAGE_CODE_FAILURE);
            	res.setStatus(ResponseVO.ERROR);
                res.setDescription((StringUtils.isEmpty(res.getDescription()) ? "" : res.getDescription()) + "\n函数名称重复，请修改！");
            }
        }
        //校验函数编码
        RuleCodeblock rc = new RuleCodeblock();
        rc.setProjectCode(codeblockVO.getRuleManage().getProjectCode());
        List<RuleCodeblock> ruleCodeblockList = this.findList(rc);
        for (RuleCodeblock codeblock : ruleCodeblockList) {
        	if(StringUtils.isEmpty(codeblock.getFunctionName())){
				continue;
			}
            if (codeblock.getFunctionName().equals(codeblockVO.getRuleCodeblock().getFunctionName()) && !codeblock.getModelCode().equals(codeblockVO.getRuleManage().getCode())) {
                res.setStatus(ResponseVO.ERROR);
                res.setDescription((StringUtils.isEmpty(res.getDescription()) ? "" : res.getDescription()) + "\n函数编码重复，请修改！");
            }
        }
        if (res.getStatus()==100) {
            return res;
        }
        RuleManage ruleManage = codeblockVO.getRuleManage();
        ruleManage.setModelType(RuleModelTypeEnum.RuleFunction.getCode());
        ruleManageService.saveOrUpdate(ruleManage);
        
        RuleCodeblock ruleCodeblock = codeblockVO.getRuleCodeblock();
        ruleCodeblock.setProjectCode(ruleManage.getProjectCode());
        ruleCodeblock.setManageId(ruleManage.getId());
        if (codeblockVO.getFuncParams() != null) {
            //过滤为空的下标项
        	List<String[]> list1=JSON.parseObject(codeblockVO.getFuncParams(), List.class);
			List<String[]> funcParams =new ArrayList<>();
			for(int i=0;i<list1.size();i++) {
				 String[] str= new String[3];
				 JSONArray secJSONArray = (JSONArray) JSONArray.toJSON(list1.get(i));
				 for(int j=0;j<secJSONArray.size();j++){
	        	        str[j]=(String)secJSONArray.get(j);
	        	    }
	        	    funcParams.add(str);
			}        	
            List<String[]> list = new ArrayList<String[]>();
            for (String[] ary : funcParams) {
                if (ary == null) continue;
                list.add(ary);
            }
            ruleCodeblock.setParameters(JSON.toJSONString(list));
        }

        ruleCodeblock.setCodeBody(ruleCodeblock.getStrCodeBody());

        super.save(ruleCodeblock);
        String funcDrl = this.genDrl(ruleManage.getProjectCode());
        RuleManage funcRuleManage = getGlobalFunc(ruleManage.getProjectCode());
        RuleVersioninfo versioninfo = new RuleVersioninfo();
        versioninfo.init(funcRuleManage, funcDrl);
        List<RuleVersioninfo> ruleList = this.ruleVersioninfoService.findList(versioninfo);
        if (ruleList != null && ruleList.size() > 0) {
            versioninfo = ruleList.get(0);
            versioninfo.setRuleContent(funcDrl);

        }
        
        
//		  //spark部分
//        RuleCodeblockSC theruleCodeblock = JSON.parseObject(JSON.toJSONString(ruleCodeblock), RuleCodeblockSC.class);
//        List<RuleDataEntity> ruleDataEntityList = dataBomService.findRuleDataEntityListByRuleManage(ruleManage);
//    	  List<RuleDataEntitySC> ruleDataEntitySCList = ClassChangeUtils.changeClassList(ruleDataEntityList);
//        CodeBlockCompile codeBlockCompile = new CodeBlockCompile(theruleCodeblock,ruleDataEntitySCList);
//        codeBlockCompile.buildCode();
//        String ruleContentJava = codeBlockCompile.getProCode();
//        String globalCode = codeBlockCompile.getGlobalCode();
//        String javaClassName = codeBlockCompile.getClassName();
//        String javaPackages = StringUtils.join(codeBlockCompile.getImportPackages(), ";");
//        String javaInnerClasses = StringUtils.join(codeBlockCompile.getInnerClasses(), ";");
//        String javaImportClasses = StringUtils.join(codeBlockCompile.getImportClasses(), ";");
//        versioninfo.setJavaClassName(javaClassName);
//        versioninfo.setRuleContentJava(ruleContentJava);
//        versioninfo.setJavaImportClasses(javaImportClasses);
//        versioninfo.setJavaPackages(javaPackages);
//        versioninfo.setJavaInnerClasses(javaInnerClasses);
//        versioninfo.setGlobalCode(globalCode);
        
        this.ruleVersioninfoService.save(versioninfo);
        this.reLoadCache(codeblockVO.getRuleManage().getProjectCode(), ruleCodeblock, ruleManage);
        return res;

    }
    /**
     * 保存并生成整个项目的函数信息
     * @param projectCode
     */
    public void saveProjectFunc(String projectCode) {
    	 String funcDrl = this.genDrl(projectCode);
         RuleManage funcRuleManage = getGlobalFunc(projectCode);
         RuleVersioninfo versioninfo = new RuleVersioninfo();
         versioninfo.init(funcRuleManage, funcDrl);
         List<RuleVersioninfo> ruleList = this.ruleVersioninfoService.findList(versioninfo);
         if (ruleList != null && ruleList.size() > 0) {
             versioninfo = ruleList.get(0);
             versioninfo.setRuleContent(funcDrl);

         }
    	 this.ruleVersioninfoService.save(versioninfo);
    }
    /**
     * 获取函数对象,每个规则项目全局相同且唯一
     */
    public static RuleManage getGlobalFunc(String projectCode) {
        RuleManage ruleManage = new RuleManage();
        ruleManage.setProjectCode(projectCode);
        ruleManage.setVersion("v1.00");
        ruleManage.setModelType(RuleModelTypeEnum.RuleFunction.getCode());
        ruleManage.setId("func_" + projectCode);
        return ruleManage;
    }

    public ResponseVO validateDrl(CodeblockVO codeblockVO,boolean isFunParam) {
    	ResponseVO msg = new ResponseVO();
        if ("math".equals(codeblockVO.getRuleCodeblock().getFuncImport())) {
//            msg.setCode("1");
        	msg.setStatus(ResponseVO.ERROR);
            return msg;
        }
        RuleModel ruleModel = new RuleModel();
        ruleModel.setRuleType(RuleType.policyrulegroup);
        ruleModel.setModelCode("test001");
        ruleModel.setModelVersion("0.01"+StringUtils.generateTenUuid());
        FunctionItem item = new FunctionItem();
        String initCode = codeblockVO.getRuleCodeblock().getInitcode();
        if(initCode==null)
        	initCode="";
        item.setFunctionBody(initCode+codeblockVO.getRuleCodeblock().getStrCodeBody().replace("&amp;", "&").replaceAll("&quot;", "\"").replaceAll("&gt;", ">").replaceAll("&lt;", "<"));
        item.setFunctionName(codeblockVO.getRuleCodeblock().getFunctionName());
        item.setReturnType(codeblockVO.getRuleCodeblock().getReturnType());
        if (codeblockVO.getFuncParams() != null) {
			List<String[]> list=JSON.parseObject(codeblockVO.getFuncParams(), List.class);
			List<String[]> funcParams =new ArrayList<>();
			for(int i=0;i<list.size();i++) {
				 String[] str= new String[3];
				 JSONArray secJSONArray = (JSONArray) JSONArray.toJSON(list.get(i));
				 for(int j=0;j<secJSONArray.size();j++){
	        	        str[j]=(String)secJSONArray.get(j);
	        	    }
	        	    funcParams.add(str);
			}
			List<String[]> params = new ArrayList<String[]>();
			for (String[] ary : funcParams) {
                if (ary == null) continue;
                params.add(new String[]{ary[1], ary[2]});
            }
            item.setParams(params);
        }
        ruleModel.getFuncList().add(item);
        if(isFunParam) {
            String funcDrl = this.genDrl(codeblockVO.getProjectCode());
            ruleModel.setFuncDrl(funcDrl);
        }
        RuleResult result = ruleService.generateRule(ruleModel);
        if (RuleResult.FAILURE.equals(result.getRetCode())) {
//            msg.setCode("0");
//            msg.setMsg(result.getRetMsg());
        	msg.setStatus(ResponseVO.ERROR);
        	msg.setDescription(result.getRetMsg());
        } else {
//            msg.setCode("1");
        	msg.setStatus(ResponseVO.OK);
        }
        return msg;
    }

    /**
     * 脚本编译，改方法已废弃，替换为compileByFlow
     */
    @Override
    public ResponseVO compile(CodeblockVO codeblockVO) throws BizException {
    	ResponseVO msg = new ResponseVO();
        File dir = null;
        try {
            String jname = "Temp" + StringUtils.generateShortUuid();
            dir =  File.createTempFile(jname, ".java");
            jname = dir.getName().replace(".java", "");
            
            String classpath = ResourceUtils.getURL("classpath:").getPath();
//            String classpath0 = RuleCodeblockServiceImpl.class.getClassLoader().getResource("/").getPath();
            File   tFile =  new  File(classpath); 
            if (!tFile.exists()){
            	String  rPath =System.getProperty(WebUtils.DEFAULT_WEB_APP_ROOT_KEY);
            	int  idx  =  classpath.lastIndexOf("/WEB-INF");
            	if (idx>-1) {
            		if (rPath.endsWith(File.separator))
            			rPath  = rPath.substring(0,rPath.length()-1);
            		classpath  = rPath +classpath.substring(idx);
            	}
            }
            // 1.创建需要动态编译的代码字符串
            String nr = "\r\n"; //回车
            StringBuilder source = new StringBuilder();
            source.append("package ").append("com.tansun.easycare.utils").append(";").append(nr).
                    append("import java.util.*;").append(nr).
                    append("import com.tansun.rule.utils.RuleHelper;").append(nr).
                    append("import com.tansun.rule.utils.DroolsRuleLog;").append(nr).
                    append("public class  ").append(jname).append("{").append(nr).
                    append("static RuleHelper ruleHelper;").append(nr).
                    append("static DroolsRuleLog droolsRuleLog;").append(nr).
                    append("static Map metaMap;").append(nr).
                    append("static Map dataMap;").append(nr).
                    append("public static void main (String[] args) throws Exception{").append(nr).
                    append(codeblockVO.getRuleCodeblock().getStrCodeBody()).append(nr).
                    append("}}");
            // 2.将欲动态编译的代码写入文件中 1.创建临时目录 2.写入临时文件目录
            FileWriter writer = null;
            try {
                writer = new FileWriter(dir);
                writer.write(source.toString());
                writer.flush();
            } catch (Exception e) {
                throw e;
            } finally {
                try {
                    if (writer != null) writer.close();
                } catch (Exception e2) {
                    throw e2;
                }
            }
      
            // 3.取得当前系统的编译器
            JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
            if(javaCompiler == null){
            	throw new RuntimeException("当前环境没有编译器, 您可能运行于JRE而不是JDK之上？");
            }
            // 4.获取一个文件管理器
            StandardJavaFileManager javaFileManager = javaCompiler.getStandardFileManager(null, null, null);
            // 5.文件管理器根与文件连接起来
            Iterable<? extends JavaFileObject> it = javaFileManager.getJavaFileObjects(dir);
            //编译参数
            int idx = classpath.indexOf("classes");
            String libpath = "";
            if (idx != -1) {
                String os = System.getProperty("os.name");
                String segmenter = ":";
                if(os.toLowerCase().startsWith("win")){  
                	segmenter = ";";
                }
                libpath = classpath.substring(0, idx) + "lib";
                libpath = this.getJarFiles(libpath,segmenter);

            }
    
//            Iterable<String> options = Arrays.asList("-classpath", libpath, "-d", classpath, "-Xlint:unchecked");
            Iterable<String> options = Arrays.asList("-encoding", "UTF-8", "-classpath", libpath, "-d", classpath);
            int status = javaCompiler.run(null, null, null, "-classpath", libpath, "-d", classpath,dir.getPath());
            //接收错误信息
            DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
            // 6.创建编译任务
            CompilationTask task = javaCompiler.getTask(null, javaFileManager, diagnostics, options, null, it);
            // 7.执行编译
            boolean suc = task.call();
            if (suc) {
//                msg.setCode("1");
                msg.setStatus(200);
            } else {
//              msg.setMsg("编译不通过");
            	msg.setDescription("编译不通过");
                
                StringBuilder errMsg = new StringBuilder();
//                msg.setCode("0");
                msg.setStatus(ResponseVO.ERROR);
                for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) {
                    String str = diagnostic.getMessage(null);
                    if (str.contains("位置")) {
                        str = str.substring(0, str.indexOf("位置"));
                    }
                    errMsg.append(str).append("<br/>");

                }
//                msg.setMsg(errMsg.toString());
                msg.setDescription(errMsg.toString());
            }

            javaFileManager.close();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
//            msg.setMsg(e.getMessage());
            msg.setDescription(e.toString());
        } finally {
            //删除临时类
            if (dir != null && dir.exists()) {
                FileUtils.deleteDirectory(dir.getPath());
            }
        }
        return msg;
    }
    

    @Override
    public ResponseVO compileByFlow(CodeblockVO codeblockVO) throws BizException {
    	ResponseVO msg = new ResponseVO();
        try {
        	String context = getFlowCode(codeblockVO);
        	DroolsComplier complier = new DroolsComplier();
        	complier.addContent(context, ResourceType.BPMN2);
        	String compileMsg = complier.complie();
        	msg.setDescription(compileMsg);
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setDescription(e.toString());
        } 
        return msg;
    }
    
    private String getJarFiles(String jarPath,final String segmenter) throws Exception {
        File sourceFile = new File(jarPath); 
        // String jars="";
        final StringBuffer sb = new StringBuffer();
        if (sourceFile.exists()) {// 文件或者目录必须存在
            if (sourceFile.isDirectory()) {// 若file对象为目录
                // 得到该目录下以.java结尾的文件或者目录
                File[] childrenFiles = sourceFile.listFiles(new FileFilter() {
                    public boolean accept(File pathname) {
                        if (pathname.isDirectory()) {
                            return true;
                        } else {
                            String name = pathname.getName();
                            if (name.endsWith(".jar")) {
                                sb.append(pathname.getPath()).append(segmenter);
                                return true;
                            }
                            return false;
                        }
                    }
                });
            }
        }
        return sb.toString();
    }

    private  void  reLoadCache(String projectCode,RuleCodeblock func,RuleManage vo) {
    	String cacheKey = DataCache.getCacheKey(projectCode, DataCache.JFUNCACHE_OPTION);
    	List<JFun> jfunList =  (List<JFun>) DataCache.getValue(cacheKey);
    	if (jfunList == null) {
    		jfunList  = new  ArrayList<>();
    	}
    	if(StringUtils.isEmpty(func.getFunctionName())){
			return;
		}
    	for (JFun qFun : jfunList) {
    		if (qFun.getId().equals(vo.getCode())) {
    			return ;
    		}
    	}
    	JFun jf = new JFun();
        String name = vo.getName();
        String id = vo.getCode();
        jf.setId(id);
        jf.setType(JFun.TYPE_JFUN);
        jf.setDataType(func.getReturnType());
        jf.setDesc(name);
        jf.setName(name);
        jf.setFunType(JFun.FT_CUST);
        jf.setLabel(name);
        if ("math".equals(func.getFuncImport())) {
            jf.setDrlName("MathHelper.invokeMath($insertMap,metaMap,\"" + new String(func.getCodeBody()) + "\"");
            jf.setShowFormat(jf.getName());
        } else {
            jf.setDrlName(func.getFunctionName() + "(");
            List<String[]> params = JSON.parseArray(func.getParameters(), String[].class);
            StringBuilder format = new StringBuilder(jf.getName()).append("-");
            if (params != null) {
                for (int i = 0; i < params.size(); i++) {
                    String[] ary = params.get(i);
                    JFunParam jfunParam = new JFunParam();
                    jfunParam.setName(ary[2]);
                    jfunParam.setDataType(ary[1]);
                    jfunParam.setSort(i);
                    jf.getParamMap().put(jfunParam.getName(), jfunParam);
                    format.append(ary[0]).append(":").append("{").append(ary[2]).append("}");
                }
            }
            jf.setShowFormat(format.toString());
        }

        jfunList.add(jf);
        DataCache.setValue(cacheKey, jfunList);

    }
    
    @SuppressWarnings("unchecked")
	@Override
    public List<JFun> genJFun(String projectCode) {
    	String cacheKey = DataCache.getCacheKey(projectCode, DataCache.JFUNCACHE_OPTION);
        if(DataCache.canGetFromCache(cacheKey)) {
        	return (List<JFun>) DataCache.getValue(cacheKey);
        }else {
        	List<JFun> jfunList = new ArrayList<JFun>();
	        // 获取主表信息
	        RuleManageVO ruleManageVO = new RuleManageVO();
	        ruleManageVO.setProjectCode(projectCode);
	        ruleManageVO.setModelType(RuleModelTypeEnum.RuleFunction.getCode());
	        List<RuleManageVO> ruleManages = ruleManageService.findRuleManageVO(ruleManageVO);
	        if (ruleManages == null || ruleManages.size() == 0) {
	            return jfunList;
	        }
	        Map<String, RuleManageVO> jfuncNames = new HashMap<String, RuleManageVO>();
	        for (RuleManageVO vo : ruleManages) {
	            jfuncNames.put(vo.getId(), vo);
	        }
	        RuleCodeblock codeInfo = new RuleCodeblock();
	        codeInfo.setProjectCode(projectCode);
	        List<RuleCodeblock> funcs = this.findList(codeInfo);
	        //组装函数对象
	        for (RuleCodeblock func : funcs) {
	        	if(StringUtils.isEmpty(func.getFunctionName())){
					continue;
				}
	            JFun jf = new JFun();
	            RuleManageVO vo = jfuncNames.get(func.getManageId());
	            if (vo == null) continue;
	            String name = vo.getName();
	            String id = vo.getCode();
	            jf.setId(id);
	            jf.setType(JFun.TYPE_JFUN);
	            jf.setDataType(func.getReturnType());
	            jf.setDesc(name);
	            jf.setName(name);
	            jf.setFunType(JFun.FT_CUST);
	            jf.setLabel(name);
	            if ("math".equals(func.getFuncImport())) {
	                jf.setDrlName("MathHelper.invokeMath($insertMap,metaMap,\"" + new String(func.getCodeBody()) + "\"");
	                jf.setShowFormat(jf.getName());
	            } else {
	                jf.setDrlName(func.getFunctionName() + "(");
	                List<String[]> params = JSON.parseArray(func.getParameters(), String[].class);
	                StringBuilder format = new StringBuilder(jf.getName()).append("-");
	                if (params != null) {
	                    for (int i = 0; i < params.size(); i++) {
	                        String[] ary = params.get(i);
	                        JFunParam jfunParam = new JFunParam();
	                        jfunParam.setName(ary[2]);
	                        jfunParam.setDataType(ary[1]);
	                        jfunParam.setSort(i);
	                        jf.getParamMap().put(jfunParam.getName(), jfunParam);
	                        format.append(ary[0]).append(":").append("{").append(ary[2]).append("}");
	                    }
	                }
	                jf.setShowFormat(format.toString());
	            }
	
	            jfunList.add(jf);
	        }
            DataCache.setValue(cacheKey, jfunList);
	        return jfunList;
        }
    }
    //获取当前项目有效函数变量
    @Override
    public String getEffectiveFunc(String projectCode) {
        RuleVersioninfo funcCondition = new RuleVersioninfo();
        funcCondition.setProjectCode(projectCode);
        funcCondition.setManageId("func_"+projectCode);
        List<RuleVersioninfo> list = this.ruleVersioninfoService.findList(funcCondition);
        if(list!=null && list.size()>0) {
            return list.get(0).getRuleContent();
        }else {
        	logger.warn("当前项目并未找到有效的函数变量！");
        }
        return "";
    }
    @Override
    public String genDrl(String projectCode) {
        RuleCodeblock codeInfo = new RuleCodeblock();
        codeInfo.setProjectCode(projectCode);
        //List<RuleCodeblock> funcs = this.findList(codeInfo);
        List<RuleCodeblock> funcs = this.dao.findParamFuncEffectAndRuleFuncList(codeInfo);
        RuleModel ruleModel = new RuleModel();
        ruleModel.setRuleType(RuleType.policyrulegroup);
        ruleModel.setModelCode("test001");
        ruleModel.setModelVersion("0.01");

        for (RuleCodeblock func : funcs) {
        	if("math".equals(func.getFuncImport())||StringUtils.isEmpty(func.getFunctionName())||StringUtils.isEmpty(func.getFuncImport())){
                continue;
            }
            FunctionItem item = new FunctionItem();
            String initCode = func.getInitcode();//RuleHelper ruleHelper = new RuleHelper(metaMap);
            if(initCode==null)
            	initCode="";
            if(func.getCodeBody() == null) {
            	func.setCodeBody("");
            }
            item.setFunctionBody(initCode+func.getCodeBody().replaceAll("&amp;", "&").replaceAll("&quot;", "\"").replaceAll("&gt;", ">").replaceAll("&lt;", "<"));

            item.setFunctionName(func.getFunctionName());
            item.setReturnType(func.getReturnType());
            if (func.getParameters() != null && !"".equals(func.getParameters())) {
                List<String[]> params = new ArrayList<String[]>();
                for (String[] ary : JSON.parseArray(func.getParameters(), String[].class)) {
                    params.add(new String[]{ary[1], ary[2]});
                }
                item.setParams(params);
            }
            
            ruleModel.getFuncList().add(item);
        }
        RuleResult result = ruleService.generateRule(ruleModel);
        if (RuleResult.FAILURE.equals(result.getRetCode())) {
            throw new RuntimeException(result.getRetMsg());
        } else {
            return result.getRetContent();
        }
    }

    @Override
    public void delCodeBlock(String manageId) throws BizException {
        RuleManage ruleManage = this.ruleManageService.get(manageId);
        RuleCodeblock ruleCodeblock = new RuleCodeblock();
        ruleCodeblock.setManageId(manageId);
        List<RuleCodeblock> list = this.findList(ruleCodeblock);
        if (list != null) {
            for (RuleCodeblock codeblock : list) {
                this.delete(codeblock);
            }
        }
        this.ruleManageService.delete(ruleManage);

    }

    @Override
    public void addFuncInfo(List<RuleVersioninfo> vList) {
        if (vList == null) {
            return;
        }

        for (RuleVersioninfo rule : vList) {
            RuleVersioninfo funcCondition = new RuleVersioninfo();
            funcCondition.setProjectCode(rule.getProjectCode());
            funcCondition.setManageId("func_"+rule.getProjectCode());
            List<RuleVersioninfo> list = this.ruleVersioninfoService.findList(funcCondition);
            if(list!=null && list.size()>0) {
                RuleVersioninfo func = new RuleVersioninfo();
                func.setModelType(RuleModelTypeEnum.RuleFunction.getCode());
                func.setRuleContent(list.get(0).getRuleContent());
                vList.add(0,func);
                System.out.println(func);
            }
            return;
//            if (RuleModelTypeEnum.PolicyRuleGroup.getCode().equals(rule.getModelType())) {
//                RuleVersioninfo func = new RuleVersioninfo();
//                func.setModelType(RuleModelTypeEnum.RuleFunction.getCode());
//                func.setRuleContent(this.genDrl(rule.getProjectCode()));
//                vList.add(func);
//                System.out.println(func);
//            }
        }


    }

    @SuppressWarnings("unchecked")
	private ResMessage copyFunction(RuleManage ruleManage) throws BizException {
        RuleCodeblock ruleCodeblock = new RuleCodeblock();
        if (ruleManage.getOldId() != null) {
            ruleCodeblock.setManageId(ruleManage.getOldId());
        } else {
            ruleCodeblock.setManageId(ruleManage.getId());
        }
        List<RuleCodeblock> list = this.findList(ruleCodeblock);
        RuleCodeblock ruleCodeblock1 = list.get(0);
        ruleCodeblock1.setId(null);
        ruleCodeblock1.setManageId(ruleManage.getId());
        ruleCodeblock1.setStrCodeBody(new String(ruleCodeblock1.getCodeBody()));
        ruleCodeblock1.setModelName(ruleCodeblock1.getModelName() + "_copy");
        ruleCodeblock1.setFunctionName(ruleCodeblock1.getFunctionName() + "_copy");
        CodeblockVO codeblockVO = new CodeblockVO();
        codeblockVO.setRuleManage(ruleManage);
        if (ruleCodeblock1.getParameters() != null) {
            codeblockVO.setFuncParams(ruleCodeblock.getParameters());
        } else {
            codeblockVO.setFuncParams(null);
        }

        ResMessage resMessage = new ResMessage();
        codeblockVO.setRuleCodeblock(ruleCodeblock1);
        try {
            this.saveFunc(codeblockVO);
        } catch (BizException e) {
            resMessage.setMsg(e.getMessage());
        }
        return resMessage;
    }

    @Override
    public void copyRule(RuleManage oldRuleManage, RuleManage ruleManage) throws BizException {
        ruleManage.setOldVersion(oldRuleManage.getVersion());
        ruleManage.setOldId(oldRuleManage.getId());
        this.copyFunction(ruleManage);
    }
    /**
     * 获取变量函数列表
     */
    public List<RuleCodeblock> findParamFuncList(RuleCodeblock condition){
    	return this.dao.findParamFuncList(condition);
    }

    @Override
    public List<RuleCodeblockInfo> findArvalFuncParamList(RuleCodeblock condition) {
        return this.dao.findArvalFuncParamList(condition);
    }

    @Override
    public List<RuleCodeblock> findParamFuncEffectList(RuleCodeblock condition) {
        return  this.dao.findParamFuncEffectList(condition);
    }

	@Override
	public String showRuleJava(String currProjectCode) {
		return currProjectCode;
/*        RuleCodeblock codeInfo = new RuleCodeblock();
        codeInfo.setProjectCode(currProjectCode);
        List<RuleCodeblock> funcs = this.dao.findParamFuncEffectAndRuleFuncList(codeInfo);
        List<com.tansun.rule.sparkCode.entity.codeblock.RuleCodeblock> funcSCs = ClassChangeUtils.<RuleCodeblock,com.tansun.rule.sparkCode.entity.codeblock.RuleCodeblock>changeClass(funcs);
		return CodeBlockCreate.createCode(funcSCs);*/
	}
	
	private String getFlowCode(CodeblockVO codeblockVO) {
		RuleManage ruleManage = codeblockVO.getRuleManage();
    	RuleCodeblock ruleCodeblock = codeblockVO.getRuleCodeblock();
    	String space = "    ";
        String wrap = "\n";
        String id = StringUtils.isEmpty(ruleManage.getCode())?"codeblockCompile":ruleManage.getCode();
        String version = StringUtils.isEmpty(ruleManage.getVersion())?"v0.01":ruleManage.getVersion();
        String name = ruleManage.getName();
        
        StringBuffer content = new StringBuffer();
        content.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + wrap);
        content.append("<definitions id=\"Definition\"" + wrap);
        content.append(space + "targetNamespace=\"http://www.jboss.org/drools\"" + wrap);
        content.append(space + "typeLanguage=\"http://www.java.com/javaTypes\"" + wrap);
        content.append(space + "expressionLanguage=\"http://www.mvel.org/2.0\"" + wrap);
        content.append(space + "xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\"" + wrap);
        content.append(space + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + wrap);
        content.append(space + "xsi:schemaLocation=\"http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd\"" + wrap);
        content.append(space + "xmlns:g=\"http://www.jboss.org/drools/flow/gpd\"" + wrap);
        content.append(space + "xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\"" + wrap);
        content.append(space + "xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\"" + wrap);
        content.append(space + "xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\"" + wrap);
        content.append(space + "xmlns:tns=\"http://www.jboss.org/drools\">" + wrap);
        content.append(wrap);

        content.append(space + "<process processType=\"Private\" isExecutable=\"true\" id=\""+id+"\" name=\""+name+"\" tns:packageName=\"com.tansun.policyrulegroup\" tns:version=\""+version+"\">" + wrap);
        content.append(space + space + "<extensionElements>" + wrap);
        content.append(space + space + space + "<tns:import name=\"java.util.*\"/>" + wrap);
        content.append(space + space + space + "<tns:import name=\"com.tansun.rule.utils.*\" />" + wrap);
        content.append(space + space + space + "<tns:import name=\"com.tansun.ruledata.data.dao.DataMiningDao\" />" + wrap);
        content.append(space + space + space + "<tns:global identifier=\"ruleHelper\" type=\"com.tansun.rule.utils.RuleHelper\" />" + wrap);
        content.append(space + space + space + "<tns:global identifier=\"droolsRuleLog\" type=\"com.tansun.rule.utils.DroolsRuleLog\" />" + wrap);
        content.append(space + space + space + "<tns:global identifier=\"dataMap\" type=\"java.util.Map\" />" + wrap);
        content.append(space + space + space + "<tns:global identifier=\"metaMap\" type=\"java.util.Map\" />" + wrap);
        content.append(space + space + "</extensionElements>" + wrap);
        content.append(wrap);
        
        content.append(space + space + "<laneSet>" + wrap);
        content.append(space + space + space + "<lane name=\"swimName01\"></lane>" + wrap);
        content.append(space + space + space + "<lane name=\"swimName02\"></lane>" + wrap);
        content.append(space + space + "</laneSet>" + wrap);
        content.append(wrap);
        content.append(space + space + "<!-- nodes -->" + wrap);

        content.append(space + space + "<startEvent id=\"start\"/>" + wrap);
        content.append(space + space + "<scriptTask id=\"test01\" name=\"Script\" scriptFormat=\"http://www.java.com/java\">" + wrap);
        String codeSc = StringEscapeUtils.escapeXml10(ruleCodeblock.getCodeBody());
        content.append(space + space + space + "<script>" + codeSc + "\r\n" + "</script>" + wrap);//脚本执行以换行符结束
        content.append(space + space + "</scriptTask>" + wrap);
        content.append(space + space + "<endEvent id=\"end\" name=\"end\"/>" + wrap);
        
        content.append(wrap);
        content.append(space + space + "<!-- connections -->" + wrap);
	    content.append(space + space + "<sequenceFlow id=\"start-test01\" sourceRef=\"start\" targetRef=\"test01\"/>" + wrap);
	    content.append(space + space + "<sequenceFlow id=\"test01-end\" sourceRef=\"test01\" targetRef=\"end\"/>" + wrap);

        content.append(space + "</process>" + wrap);
        content.append(wrap);
        content.append(space + "<bpmndi:BPMNDiagram>" + wrap);
        content.append(space + space + "<bpmndi:BPMNPlane bpmnElement=\""+id+"\">" + wrap);
        content.append(space + space + space + "<bpmndi:BPMNShape bpmnElement=\"start\">" + wrap);
        content.append(space + space + space + space + "<dc:Bounds x=\"100\" y=\"100\" width=\"110\" height=\"48\"/>" + wrap);
        content.append(space + space + space + "</bpmndi:BPMNShape>" + wrap);
        content.append(space + space + space + "<bpmndi:BPMNShape bpmnElement=\"end\">" + wrap);
        content.append(space + space + space + space + "<dc:Bounds x=\"500\" y=\"100\" width=\"110\" height=\"48\"/>" + wrap);
        content.append(space + space + space + "</bpmndi:BPMNShape>" + wrap);
        content.append(space + space + space + "<bpmndi:BPMNShape bpmnElement=\"end\">" + wrap);
        content.append(space + space + space + space + "<dc:Bounds x=\"900\" y=\"100\" width=\"110\" height=\"48\"/>" + wrap);
        content.append(space + space + space + "</bpmndi:BPMNShape>" + wrap);
        content.append(wrap);
        content.append(space + space + space + "<bpmndi:BPMNEdge bpmnElement=\"start-test01\">" + wrap);
        content.append(space + space + space + space + "<di:waypoint x=\"155\" y=\"124\"/>" + wrap);
        content.append(space + space + space + space + "<di:waypoint x=\"555\" y=\"124\"/>" + wrap);
        content.append(space + space + space + "</bpmndi:BPMNEdge>" + wrap);
        content.append(space + space + space + "<bpmndi:BPMNEdge bpmnElement=\"start-test01\">" + wrap);
        content.append(space + space + space + space + "<di:waypoint x=\"555\" y=\"124\"/>" + wrap);
        content.append(space + space + space + space + "<di:waypoint x=\"845\" y=\"124\"/>" + wrap);
        content.append(space + space + space + "</bpmndi:BPMNEdge>" + wrap);
        
        content.append(space + space + "</bpmndi:BPMNPlane>" + wrap);
        content.append(space + "</bpmndi:BPMNDiagram>" + wrap);
        content.append("</definitions>" + wrap);
        return content.toString();
	}
}
